#pragma once

#include <iostream>
#include <unordered_map>
#include "Connection.hpp"
#include "Epoller.hpp"

static const int gnum = 128;

class Reactor
{
public:
    Reactor()
        : _isRunning(false)
    {
    }

    void AddConnection(int fd, uint32_t events, func_t reader, func_t writer, func_t execpter, const InetAddr &addr = InetAddr())
    {
        // 1. 创建新连接
        Connection *con = new Connection(fd);
        con->SetEvents(events);
        con->Register(reader, writer, execpter);
        con->SetSelf(this);
        con->SetAddr(addr);

        // 2. 添加到epoll模型中
        _epoller.AddEvents(con->SockFd(), con->Events());
        // 3. 添加到容器中，以供管理
        _connections.insert(std::make_pair(con->SockFd(), con));
    }

    // 查找该连接是否存在
    bool ConnectionIsExists(int sockfd)
    {
        auto iter = _connections.find(sockfd);
        return iter != _connections.end();
    }

    void LoopOnce(int timeout)
    {
        int n = _epoller.Wait(_revs, gnum, timeout);
        for (int i = 0; i < n; i++)
        {
            int fd = _revs[i].data.fd;
            uint32_t events = _revs[i].events;

            // 将等待错误的事件全部转换为读写错误，由读写操作处理错误
            if (events & EPOLLHUP)
                events |= (EPOLLIN | EPOLLOUT);
            if (events & EPOLLERR)
                events |= (EPOLLIN | EPOLLOUT);

            // 处理读事件
            if (events & EPOLLIN)
            {
                // 由该fd对应的连接处理读事件-->要保证 1. 该连接还存在; 2. 该连接对应的_reader被注册了
                if (ConnectionIsExists(fd) && _connections[fd]->_reader != nullptr)
                {
                    _connections[fd]->_reader(_connections[fd]); // 这里是处理监听套接字的逻辑_reader对应Accept
                }
            }

            // 处理写事件
            if (events & EPOLLOUT)
            {
                // 由该fd对应的连接处理读事件-->要保证 1. 该连接还存在; 2. 该连接对应的_writer被注册了
                if (ConnectionIsExists(fd) && _connections[fd]->_writer != nullptr)
                {
                    _connections[fd]->_writer(_connections[fd]); // 这里是处理监听套接字的逻辑_reader对应Accept
                }
            }
        }
    }

    // 派发事件
    void Dispatcher()
    {
        _isRunning = true;

        int timeout = -1;
        while (true)
        {
            LoopOnce(timeout);
            Debug();
        }
        _isRunning = false;
    }

    void EnableReadWrite(int fd, bool read, bool write)
    {
        uint32_t events = ((read ? EPOLLIN : 0) | (write ? EPOLLOUT : 0) | EPOLLET);
        // 添加进内核
        _epoller.ModEvents(fd, events);
    }

    void RemoveConnection(int fd)
    {
        // 1. 从epoll模型中删除对fd的关心
        _epoller.DelEvents(fd);
        // 2. 关闭fd
        _connections[fd]->Close();
        // 3. 释放Connection对象
        delete _connections[fd];
        _connections.erase(fd);
    }

    ~Reactor()
    {
    }

    void Debug()
    {
        std::cout << "------------------------------------" << std::endl;
        for (auto &connection : _connections)
        {
            std::cout << "fd : " << connection.second->SockFd() << ", ";
            uint32_t events = connection.second->Events();
            if ((events & EPOLLIN) && (events & EPOLLET))
                std::cout << "EPOLLIN | EPOLLET, ";
            if ((events & EPOLLOUT) && (events & EPOLLET))
                std::cout << "EPOLLOUT | EPOLLET";
            std::cout << std::endl;
        }
        std::cout << "------------------------------------" << std::endl;
    }

private:
    std::unordered_map<int, Connection *> _connections;
    Epoller _epoller;
    struct epoll_event _revs[gnum];
    bool _isRunning;
};